#include "Graphics.h"
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
Graphics *Graphics::p_Graphics = NULL;

Graphics::Graphics(){
p_Graphics = this;
Cam = Camera();
Modelview = Matrix_Stack();
Projection = Matrix_Stack();

}

void Graphics::Initialize(){
    	Ready = true;
        p_Graphics = this;
		if(Cam.Lens.Load("Data\\Shaders\\Basic")){Cam.Lens.Use();}
		else{exit(1);}
		Vertex v[] = {Vertex(-1,-1,0.0,0,0),Vertex(1,-1,0.0,1,0),Vertex(1,1,0.0,1,1),Vertex(-1,1,0.0,0,1)};
		int   in[] = {0,1,2,0,3,2};
		IMAGE = new Mesh(4,6,&v[0],&in[0]);
		Models = OZBlock<Model>(3);
		Images = OZBlock<Image>(3); //TODO:Adjust for optomization
}

void Graphics::Pre_Paint(){
Cam.Lens.Use(); //use shader
glEnableVertexAttribArray(0); //allow attribs
glEnableVertexAttribArray(1);
//glEnableVertexAttribArray(2);

if(Window::p_Window!=NULL){
if(Window::p_Window->GetHeight() < 0){Window::p_Window->SetHeight(1);}//dont divide by 0;
}
glClearColor(0.5,0.5,0.5,1.0);
glClear (GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT); //make grey back screen


glDisable(GL_TEXTURE_RECTANGLE_NV); 
glEnable(GL_BLEND);
glEnable( GL_TEXTURE_2D ); 
glActiveTexture(GL_TEXTURE0);


glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);

//set up matricies
Modelview.Push();
Projection.Push();

Projection.Current->Ortho(-(SCREEN_WIDTH/2),(SCREEN_WIDTH/2),(SCREEN_HEIGHT/2),-(SCREEN_HEIGHT/2),1,-1);
Modelview.Current->Translate(0,0,-1);
}

void Graphics::Post_Paint(){

glDisable(GL_BLEND);
glDisable( GL_TEXTURE_2D ); 
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
//glDisableVertexAttribArray(2);
//glUseProgram(0);
Modelview.Pop();
Projection.Pop();
}

void Graphics::Paint(HDC hdc){
if(Ready)
{Pre_Paint();
Render();


Post_Paint();
SwapBuffers(hdc);}
}

void Graphics::Render(Sprite *Sprt){
static float mat[16];

Modelview.Push();

	//glUniform3f(Cam.Lens.MATERIAL,Dis->Material.v[0],
	//						      Dis->Material.v[1],
	//							  Dis->Material.v[2]);       //Material
	//glUniform3f(Cam.Lens.COLOR,   Dis->Color.v[0],
	//							  Dis->Color.v[1],
	//							  Dis->Color.v[2]); //Color

	glBindTexture(GL_TEXTURE_2D,Sprt->h_Image);  //Texture
	glUniform1i(Cam.Lens.TEXTURE_0,0);

	Projection.Current->GetMatrix(mat);
	glUniformMatrix4fv(Cam.Lens.PROJECTION_MATRIX,1,true,(GLfloat*)&mat[0]); //Projection

	Modelview.Current->Multiplyby(&Sprt->Orientation);
	Modelview.Current->GetMatrix(mat);
	glUniformMatrix4fv(Cam.Lens.MODELVIEW_MATRIX,1,true,(GLfloat*)&mat[0]); //Modelview

	glBindBuffer(GL_ARRAY_BUFFER,Sprt->h_Verts);
	glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(Vertex),BUFFER_OFFSET(0)); //Verticies
	glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,sizeof(Vertex),BUFFER_OFFSET(12)); //TexCoords

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,Sprt->h_Index);
	glDrawElements(GL_TRIANGLES,Sprt->IndexSize,GL_UNSIGNED_INT,BUFFER_OFFSET(0));

	Modelview.Pop();
}

